import datetime
import calendar

from django.shortcuts import render, redirect, get_object_or_404
from django.http import Http404
from django.views.generic.dates import MonthArchiveView
from django.forms import formset_factory
from django.http import JsonResponse
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.template.loader import render_to_string

from ..models import ShiftSchedule
from ..forms import (
    ShiftScheduleModelForm,
    SignInForm,
    ChangeSignInForm,
)


@login_required
def bulk_create_schedule_by_month(request, year, month):
    try:
        provide_month = datetime.date(year=year, month=month, day=1)
    except ValueError:
        raise Http404("日期出错")

    now_date = datetime.date.today()
    current_month = now_date.replace(day=1)
    pre_month = (provide_month - datetime.timedelta(days=1)).replace(day=1)

    if not (provide_month == current_month or pre_month == current_month):
        '''
        只允许创建本月和下个月的值班表
        '''
        raise Http404("{}的值班表不能创建".format(provide_month.strftime('%Y年%m月')))

    template_name = 'logs/create_schedule_by_month.html'
    formset_params = {}
    schedules_by_month = ShiftSchedule.objects.filter(duty_date__year=provide_month.year,
                                                      duty_date__month=provide_month.month)
    _, days_in_month = calendar.monthrange(provide_month.year, provide_month.month)
    if schedules_by_month.exists():
        return redirect('schedule_by_month', year=provide_month.year, month=provide_month.month)
    else:
        initial_data = [{'duty_date': datetime.date(year, month, i)} for i in range(1, days_in_month + 1)]

    formset_params['initial'] = initial_data

    ScheduleFormset = formset_factory(form=ShiftScheduleModelForm, max_num=days_in_month, min_num=days_in_month)

    if request.method == 'POST':
        formsets = ScheduleFormset(request.POST, **formset_params)
        schedule_list = []
        if formsets.is_valid():
            for form in formsets:
                if form.cleaned_data.get('duty_date'):
                    schedule_list.append(form.save(commit=False))

            ShiftSchedule.objects.bulk_create(schedule_list)

            return redirect('schedule_by_month', year=year, month=month)
    else:
        formsets = ScheduleFormset(**formset_params)

    return render(request, template_name=template_name, context={'formsets': formsets})


@method_decorator(login_required, name='dispatch')
class ScheduleMonthArchiveView(MonthArchiveView):
    queryset = ShiftSchedule.objects.all()
    ordering = ['duty_date', ]
    context_object_name = 'schedule_list'
    date_field = "duty_date"
    # make_object_list = True
    month_format = '%m'
    allow_empty = True
    allow_future = True

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data(**kwargs)
        context['mode'] = 1
        return context


def save_schedule_form(request, form, template_name, mode):
    '''
    保存修改值班表
    供签到和修改值班表调用
    :param request:
    :param form:
    :param template_name:
    :param mode: 为1时在值班表列表页使用，为2时在日志填写页使用
    :return:
    '''
    data = dict()
    if request.method == 'POST':
        if form.is_valid():
            schedule = form.save()
            year = schedule.duty_date.year
            month = schedule.duty_date.month

            data['form_is_valid'] = True
            if mode == 1:
                schedule_list = ShiftSchedule.objects.filter(duty_date__year=year, duty_date__month=month).order_by(
                    'duty_date')
                data['html_schedule_list'] = render_to_string('logs/includes/partial_schedule_list.html', {
                    'schedule_list': schedule_list,
                    'mode': mode,
                })
            elif mode == 2:
                data['html_schedule'] = render_to_string('logs/includes/common_log_form_sign_in.html', {
                    'schedule': schedule,
                    'mode': mode,
                })
            # elif mode == 3:
            # log_date = schedule.duty_date
            # datalog_list = StationDataLog.objects.filter(log_date=schedule.duty_date)
            # station_list = Station.objects.all()

            # data['html_schedule'] = render_to_string(
            #     'logs/includes/common_log_form_sign_in.html',
            #     {
            #         'schedule': schedule,
            #         'mode': mode,
            #     })
            # data['html_station_datalog_list'] = render_to_string(
            #     'logs/includes/partial_station_datalog_list.html',
            #     {
            #         'log_date': log_date,
            #         'schedule': schedule,
            #         'datalog_list': datalog_list,
            #         'station_list': station_list,
            #     })
        else:
            data['form_is_valid'] = False

    context = {'form': form, 'mode': mode}
    data['html_form'] = render_to_string(template_name, context, request=request)
    return JsonResponse(data)


def update_schedule(request, pk):
    '''
    单独修改 值班表
    :param request:
    :param pk:
    :return:
    '''
    schedule = get_object_or_404(ShiftSchedule, pk=pk)
    if request.method == 'POST':
        form = ShiftScheduleModelForm(request.POST, instance=schedule)
    else:
        form = ShiftScheduleModelForm(instance=schedule, initial={'actual_duty_person': schedule.arrange_duty_person})

    return save_schedule_form(request, form, 'logs/includes/partial_schedule_update.html', mode=1)


@login_required
def sign_in(request, pk, mode):
    '''
    签到调用函数
    :param request:
    :param pk:
    :param mode:
    :return:
    '''
    schedule = get_object_or_404(ShiftSchedule, pk=pk)
    if request.method == 'POST':
        form = SignInForm(request.POST, instance=schedule)
    else:
        form = SignInForm(instance=schedule, initial={'actual_duty_person': schedule.arrange_duty_person})

    return save_schedule_form(request, form, 'logs/includes/partial_schedule_sign_in.html', mode)


@login_required
def change_sign_in(request, pk, mode):
    '''
    修改签到调用函数
    :param request:
    :param pk:
    :param mode:
    :return:
    '''
    schedule = get_object_or_404(ShiftSchedule, pk=pk)

    if request.method == 'POST':
        form = ChangeSignInForm(request.POST, instance=schedule)
    else:
        form = ChangeSignInForm(instance=schedule)

    return save_schedule_form(request, form, 'logs/includes/partial_schedule_change_sign_in.html', mode)
